#include <map>
#include <set>

#include "../robot.h"

using namespace std;
using namespace robot;

class MyRobot: public Robot {
	set<Point> batteries;

	int random_x, random_y, random_turns;
	int treasure_x, treasure_y, treasure_turns;
	int energy_x, energy_y, energy_turns;

	public:

	virtual Action Move(const Environment& env);
};

Action MyRobot::Move(const Environment& env) {
	const double eps = 1e-3;

	Action act;

	for (map<Point, BasicSquare>::const_iterator ii = env.terrain.begin(), iiend = env.terrain.end(); ii != iiend; ++ii) {
		if (ii->second.GetEnergyContribution() > 0) {
			batteries.insert(ii->first);
		}
	}

	if (env.robots.size() && !env.turns_before_shot) {
		act.stop = true;
		act.fire = true;
		act.fire_x = int(env.robots.back().x);
		act.fire_y = int(env.robots.back().y);
		act.fire_damage = env.fire_damage_max;
	} else {
		int aim_x, aim_y;
		if ((env.energy * 2 < env.energy_max) && !energy_turns) {
			if (batteries.size()) {
				set<Point>::iterator ii = batteries.begin();
				for (int i = random() % batteries.size(); i; --i, ++ii);
				energy_x = ii->x;
				energy_y = ii->y;
				energy_turns = env.width + env.height;
			}
		}
		if (energy_turns) {
			if (const_cast<Environment&>(env).terrain[Point(int(env.x), int(env.y))].GetEnergyContribution() > 0) {
				energy_x = int(env.x);
				energy_y = int(env.y);
			}
			aim_x = energy_x;
			aim_y = energy_y;
			--energy_turns;
		} else {
			if (env.treasures.size() && !treasure_turns) {
				const Point& p = env.treasures[random() % env.treasures.size()];
				treasure_x = p.x;
				treasure_y = p.y;
				treasure_turns = 40;
			}
			if (treasure_turns) {
				aim_x = treasure_x;
				aim_y = treasure_y;
				--treasure_turns;
			} else {
				if (!random_turns) {
					random_x = random() % env.width;
					random_y = random() % env.height;
					random_turns = env.width + env.height;
				}
				aim_x = random_x;
				aim_y = random_y;
				--random_turns;
			}
		}
		if (int(env.x) == aim_x && int(env.y) == aim_y) {
			act.stop = true;
			if (aim_x == energy_x && aim_y == energy_y) {
				energy_turns = env.energy_max > env.energy;
			}
			if (aim_x == treasure_x && aim_y == treasure_y) {
				treasure_turns = 0;
			}
			if (aim_x == random_x && aim_y == random_y) {
				random_turns = 0;
			}
		}

		if (aim_x + 1.0 - eps < env.x && env.vx > 0) {
			act.stop = true;
		} else if (aim_y + 1.0 - eps < env.y && env.vy > 0) {
			act.stop = true;
		} else if (aim_x > env.x && env.vx < 0) {
			act.stop = true;
		} else if (aim_y > env.y && env.vy < 0) {
			act.stop = true;
		} else {
			if (aim_x == int(env.x)) {
				if (env.vx > 0) {
					act.ax = -1;
				} else if (env.vx < 0) {
					act.ax = 1;
				}
			} else if (aim_x < env.x) {
				act.ax = -1;
			} else if (env.x < aim_x) {
				act.ax = 1;
			}
			if (aim_y == int(env.y)) {
				if (env.vy > 0) {
					act.ay = -1;
				} else if (env.vy < 0) {
					act.ay = 1;
				}
			} else if (aim_y < env.y) {
				act.ay = -1;
			} else if (env.y < aim_y) {
				act.ay = 1;
			}
		}
	}

	return act;
}

extern "C" {
	robot::Robot* getRobot() {
		return new MyRobot();
	}
}
